Add support for Jelbert GeoTagger data files (.jtr).
authoroliskoli <oliskoli>
Sat, 20 Sep 2008 19:44:43 +0000 (19:44 +0000)
committeroliskoli <oliskoli>
Sat, 20 Sep 2008 19:44:43 +0000 (19:44 +0000)
Makefile.in
geotagger.c [new file with mode: 0644]
vecs.c

index 26a798b322b99d2966b117d63228562a2fd5a0af..bb0b9b5049d6d5f8ccd4efa2972ffadd8f5dd35c 100644 (file)
@@ -59,7 +59,8 @@ ALL_FMTS=$(MINIMAL_FMTS) gtm.o gpsutil.o pcx.o cetus.o copilot.o \
        wbt-200.o stmsdf.o gtrnctr.o dmtlog.o raymarine.o alan.o vitovtt.o \
        ggv_log.o g7towin.o garmin_gpi.o lmx.o random.o xol.o dg-100.o \
        navilink.o mtk_logger.o ik3d.o osm.o destinator.o exif.o vidaone.o \
-       igo8.o gopal.o humminbird.o mapasia.o gnav_trl.o navitel.o ggv_ovl.o
+       igo8.o gopal.o humminbird.o mapasia.o gnav_trl.o navitel.o ggv_ovl.o \
+       geotagger.o
 
 FMTS=@FMTS@
 
@@ -503,6 +504,8 @@ geoniche.o: geoniche.c defs.h config.h queue.h gbtypes.h zlib/zlib.h \
   jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
   jeeps/gpsmath.h jeeps/gpsmem.h jeeps/gpsrqst.h jeeps/gpsinput.h \
   jeeps/gpsproj.h garmin_tables.h
+geotagger.o: geotagger.c defs.h config.h queue.h gbtypes.h zlib/zlib.h \
+  zlib/zconf.h gbfile.h cet.h cet_util.h csv_util.h
 ggv_log.o: ggv_log.c defs.h config.h queue.h gbtypes.h zlib/zlib.h \
   zlib/zconf.h gbfile.h cet.h cet_util.h inifile.h grtcirc.h \
   jeeps/gpsmath.h jeeps/gps.h jeeps/../defs.h jeeps/gpsport.h \
diff --git a/geotagger.c b/geotagger.c
new file mode 100644 (file)
index 0000000..7f08ad0
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+
+    Support for the Jelbert GeoTagger JTR data file format.
+
+    Copyright (C) 2008 Olaf Klein, o.b.klein@gpsbabel.org
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include <ctype.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include "defs.h"
+#include "csv_util.h"
+#include "avltree.h"
+
+#define MYNAME "geotagger"
+
+static
+arglist_t geotagger_args[] = {
+       ARG_TERMINATOR
+};
+
+static gbfile *fin, *fout;
+static avltree_t *trkpts;
+
+static time_t
+geotagger_parse_time(const char *str, struct tm *tm, int *micro)
+{
+       long int hms;
+       char *dot;
+
+       hms = strtol(str, &dot, 10);
+       if (hms > 0) {
+               tm->tm_sec = hms % 100;
+               hms = hms / 100;
+               tm->tm_min = hms % 100;
+               hms = hms / 100;
+               tm->tm_hour = hms % 100;
+
+               if ((*dot == '.') && (micro != NULL)) *micro = atoi(dot + 1) * 10000;
+
+               return mkgmtime(tm);
+       }
+       else return 0;
+}
+
+static time_t
+geotagger_parse_date(const char *str, struct tm *tm)
+{
+       int dmy = atoi(str);
+
+       if (dmy > 0) {
+               tm->tm_year = dmy % 100 + 100;
+               dmy = dmy / 100;
+               tm->tm_mon  = dmy % 100 - 1;
+               dmy = dmy / 100;
+               tm->tm_mday = dmy;
+               return mkgmtime(tm);
+       }
+       else return 0;
+}
+
+/*******************************************************************************
+* %%%        global callbacks called by gpsbabel main process              %%% *
+*******************************************************************************/
+
+static void
+geotagger_rd_init(const char *fname)
+{
+       fin = gbfopen(fname, "r", MYNAME);
+       trkpts = avltree_init(0, MYNAME);
+}
+
+static void
+geotagger_rd_deinit(void)
+{
+       avltree_done(trkpts);
+       gbfclose(fin);
+}
+
+static void
+geotagger_read(void)
+{
+       char *str;
+       int line = 0;
+       route_head *trk = NULL;
+
+       while ((str = gbfgetstr(fin))) {
+               waypoint *wpt;
+               struct tm tm;
+               char *tmp;
+               int column = -1;
+               char valid = 'V';
+               double lat, lon;
+               float speed, course, mcourse, mvar, mdev;
+               time_t time = 0;
+               int micros = 0;
+               char buf[32];
+               char mvardir, mdevdir;
+
+               line++;
+
+               str = lrtrim(str);
+               if (*str == '\0') continue;
+
+               if (strncmp(str, "GEOTAG2,", 8) != 0)
+                       fatal(MYNAME ": Unknown or unsupported file (missing \"GEOTAG2\")!\n");
+
+               memset(&tm, 0, sizeof(tm));
+               lat = lon = 999;
+               speed = course = mcourse = mvar = mdev = -1;
+               mvardir = mdevdir = 0;
+
+               column = -1;
+               tmp = str;
+               while ((str = csv_lineparse(tmp, ",", "", column++))) {
+                       tmp = NULL;
+
+                       if (*str == '\0') continue;
+
+                       switch(column) {
+                               case 0: break;          /* GEOTAG2 */
+                               case 1: geotagger_parse_time(str, &tm, &micros); break;
+                               case 2: valid = *str; break;
+                               case 3: lat = ddmm2degrees(atof(str)); break;
+                               case 4: if (*str == 'S') lat *= -1; break;
+                               case 5: lon = ddmm2degrees(atof(str)); break;
+                               case 6: if (*str == 'W') lon *= -1; break;
+                               case 7: speed = KNOTS_TO_MPS(atof(str)); break;
+                               case 8: course = atof(str); break;
+                               case 9: geotagger_parse_date(str, &tm); break;
+                               case 13: mcourse = atof(str); break;
+                               case 14: mdev = atof(str); break;
+                               case 15: mdevdir = *str; break;
+                               case 16: mvar = atof(str); break;
+                               case 17: mvardir = *str; break;
+                               default:
+                                       break;
+                       }
+               }
+
+               if ((lat == 999) || (lon == 999) || (valid != 'A')) continue;
+
+               if (tm.tm_year > 0) time = mkgmtime(&tm);
+               else time = 0;
+
+               /* check for duplicates as suggested in format description */
+
+               snprintf(buf, sizeof(buf), "%.6f\01\%.6f\01\%ld", lat, lon, (long)time);
+               if (avltree_find(trkpts, buf, NULL)) continue;
+
+               wpt = waypt_new();
+
+               wpt->latitude = lat;
+               wpt->longitude = lon;
+               wpt->creation_time = time;
+               wpt->microseconds = micros;
+               if (speed >= 0) WAYPT_SET(wpt, speed, speed);
+               if (mcourse >= 0) {
+                       course = mcourse;
+                       if (mvar >= 0) {
+                               if (mvardir == 'W') course += mvar;
+                               else if (mvardir == 'E') course -= mvar;
+                       }
+                       if (mdev >= 0) {
+                               if (mdevdir == 'W') course += mdev;
+                               else if (mdevdir == 'E') course -= mdev;
+                       }
+               }
+               if (course >= 0) WAYPT_SET(wpt, course, course);
+
+               if (trk == NULL) {
+                       trk = route_head_alloc();
+                       track_add_head(trk);
+               }
+
+               avltree_insert(trkpts, buf, wpt);
+               track_add_wpt(trk, wpt);
+               xfree(str);
+       }
+}
+
+static void
+geotagger_wr_init(const char *fname)
+{
+       fout = gbfopen(fname, "wb", MYNAME);
+}
+
+static void
+geotagger_wr_deinit(void)
+{
+       gbfclose(fout);
+}
+
+static void
+geotagger_trkpt_disp_cb(const waypoint *wpt)
+{
+       char *str, *tmp;
+       char stime[10], sdate[7], scourse[6], sspeed[8];
+       struct tm tm;
+
+       if (wpt->creation_time > 0) {
+               tm = *gmtime(&wpt->creation_time);
+               tm.tm_year += 1900;
+               tm.tm_mon += 1;
+               snprintf(sdate, sizeof(sdate), "%02d%02d%02d", tm.tm_mday, tm.tm_mon, tm.tm_year % 100);
+               snprintf(stime, sizeof(stime), "%02d%02d%02d.%02d", tm.tm_hour, tm.tm_min, tm.tm_sec, wpt->microseconds / 10000);
+               if (wpt->microseconds / 10000 == 0) stime[6] = 0;
+       }
+       else {
+               stime[0] = 0;
+               sdate[0] = 0;
+       }
+       if (WAYPT_HAS(wpt, speed) && (wpt->speed >= 0))
+               snprintf(sspeed, sizeof(sspeed), "%.1f", MPS_TO_KNOTS(wpt->speed));
+       else sspeed[0] = 0;
+       if (WAYPT_HAS(wpt, course) && (wpt->course >= 0))
+               snprintf(scourse, sizeof(scourse), "%.1f", wpt->course);
+       else scourse[0] = 0;
+
+       xasprintf(&str, "GEOTAG2,%s,%c,%09.4f,%c,%010.4f,%c,%s,%s,%s,,E,A",
+               stime,
+               time > 0 ? 'A' : 'V',
+               fabs(degrees2ddmm(wpt->latitude)),
+               wpt->latitude < 0 ? 'S' : 'N',
+               fabs(degrees2ddmm(wpt->longitude)),
+               wpt->longitude < 0 ? 'W' : 'E',
+               sspeed,
+               scourse,
+               sdate);
+
+       xasprintf(&tmp, "%s*%02X", str, nmea_cksum(str));
+       xfree(str);
+       str = tmp;
+
+       xasprintf(&tmp, "%s,,,E,,E*%02X\n", str, nmea_cksum(str));
+       xfree(str);
+       str = tmp;
+
+       gbfputs(str, fout);
+       xfree(str);
+}
+
+static void
+geotagger_write(void)
+{
+       track_disp_all(NULL, NULL, geotagger_trkpt_disp_cb);
+}
+
+/**************************************************************************/
+
+ff_vecs_t geotagger_vecs = {
+       ff_type_file,
+       {
+               ff_cap_none,                    /* waypoints */
+               ff_cap_read | ff_cap_write,     /* tracks */
+               ff_cap_none                     /* routes */
+       },
+       geotagger_rd_init,
+       geotagger_wr_init,
+       geotagger_rd_deinit,
+       geotagger_wr_deinit,
+       geotagger_read,
+       geotagger_write,
+       NULL,
+       geotagger_args,
+       CET_CHARSET_ASCII, 0                    /* ascii is the expected character set */
+                                               /* not fixed, can be changed through command line parameter */
+};
+
+/**************************************************************************/
diff --git a/vecs.c b/vecs.c
index 9ce270d0690860fd444c575bd209cbe387b567bf..abfb2f3c83f53c5bbbff4d063e3ca0e433700f81 100644 (file)
--- a/vecs.c
+++ b/vecs.c
@@ -147,6 +147,9 @@ extern ff_vecs_t mapasia_tr7_vecs;
 extern ff_vecs_t gnav_trl_vecs;
 extern ff_vecs_t navitel_trk_vecs;
 extern ff_vecs_t ggv_ovl_vecs;
+#if CSVFMTS_ENABLED
+extern ff_vecs_t geotagger_vecs;
+#endif
 
 static
 vecs_t vec_list[] = {
@@ -844,6 +847,14 @@ vecs_t vec_list[] = {
                 "Geogrid-Viewer ascii overlay file (.ovl)",
                 "ovl"
         },
+#if CSVFMTS_ENABLED
+        {
+                &geotagger_vecs,
+                "geotagger",
+                "Jelbert GeoTagger data file",
+                "jtr"
+        },
+#endif
 
 #endif // MAXIMAL_ENABLED
        {